package com.mintyfresh.tns.client;

import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import com.mintyfresh.tns.util.*;

public class Client {

	private static BufferedReader stdIn = null;
	private static ObjectOutputStream out = null;
	private static Properties properties = new Properties();

	private static GameWindow gameWindow;

	private static JFrame loginWindowFrame;
	private static JFrame gameWindowFrame;

	private static JTextField ipAddress;
	private static JTextField port;
	private static JTextField name;

	private static boolean loggedIn = false;
	private static String username;
	private static boolean finished = false;

	public static void main(String[] args) {
		if (args.length == 3) {
			try {
				connect(args[0], new Integer(args[1]).intValue(), args[2]);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			//get login info
			JFrame loginWindowFrame = new JFrame("Login");
			Container loginPane = loginWindowFrame.getContentPane();
			JLabel ipAddressLabel = new JLabel("IP Address");
			ipAddress = new JTextField(12);
			JLabel portLabel = new JLabel("Port");
			port = new JTextField(5);
			JLabel nameLabel = new JLabel("User Name");
			name = new JTextField(12);
			JButton sendButton = new JButton("Connect");
			loginPane.setLayout(new GridLayout(4, 2));
			loginPane.add(ipAddressLabel);
			loginPane.add(ipAddress);
			loginPane.add(portLabel);
			loginPane.add(port);
			loginPane.add(nameLabel);
			loginPane.add(name);
			loginPane.add(sendButton);
			sendButton.addActionListener(new ConnectListener());
			loginWindowFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			loginWindowFrame.pack();
			loginWindowFrame.setVisible(true);

			while(!loggedIn) {}
			loginWindowFrame.dispose();
		}

		//create game window
		gameWindowFrame = new JFrame("Tanks N' Stuff");
		Container pane = gameWindowFrame.getContentPane();
		gameWindow = new GameWindow();
		Dimension d = new Dimension(810, 628);
		pane.add(gameWindow);
		gameWindowFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gameWindowFrame.setSize(d);
		gameWindowFrame.setMaximumSize(d);
		gameWindowFrame.setVisible(true);

		//infinite loop until kill() is called
		while(!finished){}
		System.exit(0);
	}

	/**
	 * Hook for button listener to use
	 */
	public static void connect() {
		try {
			connect(ipAddress.getText(), new Integer(port.getText()).intValue(), name.getText());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * connect
	 * Client connection request to the Server.
	 *
	 * @param  ip IP address
	 * @param  port Connection port
	 * @param  username Client-requested username for the game
	 */
	private static void connect(String ip, int port, String username) throws Exception {
		try {
			Socket socket = new Socket(ip, port);
			out = new ObjectOutputStream(socket.getOutputStream());
			stdIn = new BufferedReader(new InputStreamReader(System.in));

			ClientListener listener = new ClientListener(socket);
			listener.start();

			Message msg = new Message("newPlayer");
			msg.set("username", username);
			send(msg);
		} catch (IOException e) {
			throw new Exception(e.getMessage());
		}
	}

	public static void connected(Message unused) {
		loggedIn = true;
	}

	/**
	 * shoot
	 * Initiates a shot from the Client to the Server.
	 *
	 * @param  power Integer value of power for player's shot.
	 * @param  angle Integer value between 0-180 for angle of player's shot
	 */
	public static void sendShot(int power, int angle) {
		Message msg = new Message("shot");
		msg.set("power", power);
		msg.set("angle", angle);
		send(msg);
	}

	public static void newRound(Message msg) {
		gameWindow.newRound(
				(Terrain)msg.get("terrain"),
				(Physics)msg.get("engine"),
				(HashMap<String, Pair>)msg.get("players"));
	}

	public static void signalPlayerTurn(Message unused) {
		gameWindow.signalPlayerTurn();
	}

	public static void shotResults(Message msg) {
		gameWindow.shotResults(
				(Pair)msg.get("origin"),
				msg.geti("power"),
				msg.getd("angle"));
	}

	public static void endRound(Message msg) {
		gameWindow.endRound();
	}

	public static void badUsername(Message msg) {
		String[] names = (String[])msg.get("names");
		JOptionPane.showMessageDialog(gameWindowFrame, "Invalid Username, please try again. Names taken:\n" + names);
		System.exit(0);
	}

	public static void endGame(Message unused) {
		finished = true;
	}

	/**
	 * disconnect
	 * Initiates a clean disconnection from the Server
	 */
	public static void disconnect(){
		Message msg = new Message("disconnect");
		send(msg);
		ClientListener.kill();
		System.exit(1);
	}

	private static void send(Object objectOut){
		try {
			out.writeObject(objectOut);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
